#ifndef __ADDROBJ__H__
#define __ADDROBJ__H__

#include <linux/types.h>

#define PROC_PATH	"/proc/sys/leadsec/netobj/addr_range"

#ifndef ADDR_DEBUG
#define ADDR_DEBUG
#endif

#ifdef ADDR_DEBUG
#define duprintf( format, args... ) printk( "%s %d: " format , __FUNCTION__, __LINE__, ## args )
#else
#define duprintf( format, args... )
#endif

#ifndef MAX_OBJ_NAME_LEN
#define MAX_OBJ_NAME_LEN        64
#endif

typedef unsigned char u8;
typedef unsigned int u32;

#define ADDR_RANGE_OBJ_BASE 	2048
enum addrobj_sockopt_set_cmds {
	ADDR_RANGE_OBJ_ADD = ADDR_RANGE_OBJ_BASE,
	ADDR_RANGE_OBJ_DELETE,
	ADDR_RANGE_OBJ_FLUSH,
	ADDR_RANGE_CELL_ADD,
	ADDR_RANGE_CELL_DELETE,
	ADDR_RANGE_CELL_FLUSH,
	ADDR_RANGE_OBJ_SET_MAX,
};

enum addrobj_sockop_get_cmds {
	ADDR_RANGE_OBJ_EXIST = ADDR_RANGE_OBJ_BASE,
	ADDR_RANGE_OBJ_GET_MAX,
};

enum {
	ADDROBJ_SRC     = 1 << 0,	/* match source IP address */
	ADDROBJ_DST     = 1 << 1,	/* match destination IP address */
	ADDROBJ_INV 	= 1 << 4,		/* negate */
};

enum {
	ADDR_IPV4 = 0,
	ADDR_IPV6,
	ADDR_TYPE_MAX,
};

/*add,modify,show addr-range object command communication data structure*/
typedef struct addr_range {
	union nf_inet_addr startip;
	union nf_inet_addr endip;
	
} addr_range_t;

typedef struct addr_range_request {
	char name[MAX_OBJ_NAME_LEN];
	u8 family;
	u8 flags;
	addr_range_t range;
	size_t size;
	
} addr_range_request_t;

#ifdef __KERNEL__

/* Addr item operation func */
typedef int ( *addr_item_destroy )( void * );

/* Addr cell operation func */
typedef void ( *addr_cell_destroy )( void *, void * );

typedef struct addr_range_cell {
	struct list_head list;	
	addr_range_t range;
	u8 family;
	u8 index;	/* addr type index */
	u8 flags;		/* negate */
	size_t size;
	rwlock_t lock;
	atomic_t refcnt;
	atomic_t num;
	addr_cell_destroy destroy;
	
} addr_range_cell_t;

typedef struct addr_range_item {
	struct list_head list;
	struct list_head head;
	char name[MAX_OBJ_NAME_LEN];
	u8 family;
	u8 index;
	rwlock_t lock;
	atomic_t refcnt;
	atomic_t num;
	addr_item_destroy destroy;
	size_t size;
	
} addr_range_item_t;

typedef struct addr_type {
	struct list_head head;
	class_cfg_t cfg;
	
} addr_type_t;

/* Export API for addrobj_std.c */
struct sk_buff;

extern class_item_t addr_range_class;

extern addr_range_item_t * addr_range_find_obj( const char *name, unsigned char flags );
extern void addr_range_bind_obj( unsigned long addr );
extern void addr_range_release_obj( unsigned long obj_addr );
extern int addr_range_matchv4_func( unsigned long obj_addr, const u32 *srcip );
extern int addr_range_matchv6_func( unsigned long obj_addr, const struct in6_addr *ip );
extern int addr_range_clean_resource( void );


extern int addr_range_construct_item( addr_range_request_t *req );
extern int addr_range_destruct_item( addr_range_request_t *req );
extern int addr_range_construct_cell( addr_range_request_t *req );
extern int addr_range_destruct_cell( addr_range_request_t *req );
extern int addr_range_flush_item( addr_range_request_t *req );
extern int addr_range_exist_item( addr_range_request_t *req );

/* Porc api */
extern int addrange_obj_proc_init( void );
extern void addrange_obj_proc_fint( void );
extern int addr_range_list_init( void );
extern void addr_range_list_free( void );

#endif	/* __KERNEL__ */

#endif	/* __ADDROBJ__H__ */
